<?php

namespace app\api\controller;

use app\api\model\Manager;
use app\api\model\SysSetting;
use app\common\logic\Auth;
use think\facade\Validate;
use app\common\service\QlRedis;
use app\common\service\Wwork;
use app\common\Verify;
use app\lib\Result;
use Yurun\Util\HttpRequest;

class Login extends \app\BaseController
{
  protected $redis;
  public function initialize()
  {
    allowCORS();
    $this->redis = new QlRedis();
  }
  public function login()
  {
    $type = input('param.type');
    if ($type == 'wx_login') {
      return self::wechat_login($this->redis);
    }elseif($type == 'ww_login') {
      return self::ww_login($this->redis);
    }
    if (request()->isPost()) {
      $ip = get_client_ip();
      $rule = [
        'token|智能验证信息'  => 'require',
        'authenticate|智能验证信息'  => 'require',
        'username|用户名/手机号' => 'min:5',
        'password|密码' => 'min:8|max:26',
        'phone|手机号' => 'mobile',
        'captcha|验证码' => 'number',
      ];
      $data = [
        'token'  => input('param.token', '', 'trim'),
        'authenticate'  => input('param.authenticate', '', 'trim'),
        'username'  => input('param.username/s', '', 'trim'),
        'password'  => input('param.password/s', '', 'trim'),
        'phone'  => input('param.mobile/s', '', 'trim'),
        'captcha'  => input('param.captcha/s', '', 'trim'),
      ];
      $validate = Validate::rule($rule);
      $result   = $validate->check($data);
      if (!$result) {
        return Result::Error($validate->getError());
      }
      // if (!checkphone($data['username'])) {
      //   return Result::Error('手机号格式不正确');
      // }
      if (empty($data['username']) && empty($data['password']) && empty($data['phone']) && empty($data['captcha'])) {
        return Result::Error('登录信息不能都为空');
      }
      $opData['title'] = '管理登录';
      $time = time();
      if (!empty($data['username']) && !empty($data['password'])) {
        $dataVerify['token'] = $data['token'];
        $dataVerify['authenticate'] = $data['authenticate'];
        Verify::check($dataVerify);
        $hasUser = Manager::field('id,salt,password,phone,login_times,is_admin,groupId,status,username,avatar')->where('phone|username', $data['username'])->find();
        if (empty($hasUser)) {
          $opData['uid'] = 0;
          $opData['username'] = $data['username'];
          $opData['ext_log'] = '查询不到用户';
          $opData['opstatus'] = -1;
          addOpLog($opData);
          $limitResult = limitResult('managerlogin', $ip);
          if ($limitResult['code'] != -1) {
            return Result::Error('帐号或密码不正确');
          } else {
            return Result::Error($limitResult['msg']);
          }
        }
        if ($hasUser['status'] != 1) {
          return Result::Error('用户状态异常或被封禁，请联系上级管理进行处理。');
        }
        $saltPassword = md5($data['password'] . $hasUser['salt']);
        if ($saltPassword != $hasUser['password']) {
          $opData['uid'] = (int) $hasUser['id'];
          $opData['username'] = $data['username'];
          $opData['ext_log'] = '登录密码错误，错误密码为：' . $data['password'];
          $opData['opstatus'] = -1;
          addOpLog($opData);
          $limitResult = limitResult('managerlogin', $ip);
          if ($limitResult['code'] != -1) {
            return Result::Error('帐号或密码不正确，请确认后重新登录');
          } else {
            return Result::Error($limitResult['msg']);
          }
        }
      } else {
        $hasUser = Manager::field('id,salt,password,phone,login_times,is_admin,groupId,status,username,avatar')->where('phone', $data['phone'])->find();
        if (empty($hasUser)) {
          $opdata['uid'] = 0;
          $opdata['username'] = $data['phone'];
          $opdata['ext_log'] = $data['phone'] . '未注册，无法登录';
          $opdata['opstatus'] = -1;
          addOpLog($opdata);
          $limitResult = limitResult('managerlogin', $ip);
          if ($limitResult['code'] != -1) {
            return Result::Error('该手机号未注册');
          } else {
            return Result::Error($limitResult['msg']);
          }
        }
        $sms_code = $this->redis->get('smsCode:' . $data['phone']);
        if (empty($sms_code) || ($sms_code != $data['captcha'])) {
          return Result::Error('验证码已过期或不存在，请重新获取！');
        }
        $this->redis->del('smsCode:' . $data['phone']);
      }
      //更新会员状态
      $param = [
        'login_times' => $hasUser['login_times'] + 1,
        'login_ip' => $ip,
        'login_time' => $time,
      ];
      $opData['uid'] = (int) $hasUser['id'];
      $opData['username'] = $hasUser['phone'];
      $opData['ext_log'] = '登录成功';
      $opData['opstatus'] = 1;
      addOpLog($opData);
      Manager::where('id', $hasUser['id'])->update($param);
      $payload['uid']       = $hasUser['id'];
      $payload['password']       = $hasUser['password'];
      $payload['loginTime'] = $time;
      $payload['refresh_key'] = createId();
      $rules = Auth::getRuleId($hasUser['groupId']);
      $tokenArr['rules'] = Auth::getRuleKey($rules);
      $token = think_encrypt(json_encode($payload));
      $tokenArr['userToken'] = $token;
      //用户登录有效期
      $loginRefreshExpireTime = config('app.SYS_STATIC.login_refresh_expire');
      $loginExpireTime = config('app.SYS_STATIC.login_expire');
      // 存储用户刷新token
      $this->redis->set('token-' . $hasUser['id'], $token, $loginExpireTime);
      $this->redis->set('refresh:key:' . $payload['refresh_key'], json_encode($payload), $loginRefreshExpireTime);
      $tokenArr['Expire'] = $loginRefreshExpireTime * 1000;
      $tokenArr['loginExpire'] = ($loginExpireTime + $time)*1000;
      $tokenArr['isSuper'] = $hasUser['is_admin'];
      $tokenArr['username'] = $hasUser['username'];
      $tokenArr['avatar'] = $hasUser['avatar'];
      return Result::Success($tokenArr, '登录成功，页面将自动跳转……');
    }
    return Result::Error('请求不正常');
  }
  private static function wechat_login($redis)
  {
    $ip = get_client_ip();
    if (request()->isPost()) {
      $rule = [
        'code'  => 'require',
      ];
      $data = [
        'code'  => input('param.code', '', 'trim'),
      ];
      $validate = Validate::rule($rule);
      $result   = $validate->check($data);
      if (!$result) {
        return Result::Error($validate->getError());
      }
      $wechat_setting = SysSetting::where('id', 1)->find();
      $accessUrl = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $wechat_setting['wechat_appid'] . '&secret=' . $wechat_setting['wechat_secret'] . '&code=' . $data['code'] . '&grant_type=authorization_code';
      $http = new HttpRequest;
      $getAccessToken = $http->get($accessUrl);
      $data = json_decode($getAccessToken->body(), true);
      if (isset($data['errmsg'])) {
        return Result::Error('微信登录：获取access_token失败 Msg:' . $data['errmsg']);
      }
      $infoUrl = 'https://api.weixin.qq.com/sns/userinfo?access_token=' . $data['access_token'] . '&openid=' . $data['openid'];
      $getAccessToken = $http->get($infoUrl);
      $data = json_decode($getAccessToken->body(), true);
      if (isset($data['errmsg'])) {
        return Result::Error('微信登录：获取用户信息失败 Msg:' . $data['errmsg']);
      }
      $opData['title'] = '管理登录';
      $time = time();
      if (isset($data['unionid']) && !empty($data['unionid'])) {
        $hasUser = Manager::field('id,salt,password,phone,login_times,is_admin,groupId,status,username,avatar')->where('wechat_union_id', $data['unionid'])->find();
      } else {
        $hasUser = Manager::field('id,salt,password,phone,login_times,is_admin,groupId,status,username,avatar')->where('wechat_open_id', $data['openid'])->find();
      }
      if (empty($hasUser)) {
        $opData['uid'] = 0;
        $opData['username'] = $data['nickname'];
        $opData['ext_log'] = '[微信授权]查询不到用户';
        $opData['opstatus'] = -1;
        addOpLog($opData);
        $limitResult = limitResult('managerlogin', $ip);
        if ($limitResult['code'] != -1) {
          return Result::Error('未绑定平台账号');
        } else {
          return Result::Error($limitResult['msg']);
        }
      }
      if ($hasUser['status'] != 1) {
        return Result::Error('用户状态异常或被封禁，请联系上级管理进行处理。');
      }
      if (empty($hasUser['avatar'])) {
        $param['avatar'] = $hasUser['avatar'] = $data['headimgurl'];
      }
      //更新会员状态
      $param = [
        'login_times' => $hasUser['login_times'] + 1,
        'login_ip' => $ip,
        'login_time' => $time,
      ];
      $opData['uid'] = (int) $hasUser['id'];
      $opData['username'] = $hasUser['phone'];
      $opData['ext_log'] = '登录成功';
      $opData['opstatus'] = 1;
      addOpLog($opData);
      Manager::where('id', $hasUser['id'])->update($param);
      $payload['uid']       = $hasUser['id'];
      $payload['password']       = $hasUser['password'];
      $payload['loginTime'] = $time;
      $payload['refresh_key'] = createId();
      $rules = Auth::getRuleId($hasUser['groupId']);
      $tokenArr['rules'] = Auth::getRuleKey($rules);
      $token = think_encrypt(json_encode($payload));
      $tokenArr['userToken'] = $token;
      //用户登录有效期
      $loginExpireTime = config('app.SYS_STATIC.login_expire');
      $loginRefreshExpireTime = config('app.SYS_STATIC.login_refresh_expire');
      // 存储用户token
      $redis->set('token-' . $hasUser['id'], $token, $loginExpireTime);
      $redis->set('refresh:key:' . $payload['refresh_key'], json_encode($payload), $loginRefreshExpireTime);
      $tokenArr['Expire'] = $loginExpireTime * 1000;
      $tokenArr['isSuper'] = $hasUser['is_admin'];
      $tokenArr['username'] = $hasUser['username'];
      $tokenArr['avatar'] = $hasUser['avatar'];
      return Result::Success($tokenArr, '登录成功，页面将自动跳转……');
    }
    return Result::Error('请求不正常');
  }
  private static function ww_login($redis)
  {
    $ip = get_client_ip();
    if (request()->isPost()) {
      $rule = [
        'code'  => 'require',
      ];
      $data = [
        'code'  => input('param.code', '', 'trim'),
      ];
      $validate = Validate::rule($rule);
      $result   = $validate->check($data);
      if (!$result) {
        return Result::Error($validate->getError());
      }
      $data = (new Wwork)->getUserInfo($data['code']);
      $opData['title'] = '管理登录';
      $time = time();
      $hasUser = Manager::field('id,salt,password,phone,login_times,is_admin,groupId,status,username,avatar')->where('ww_user_id', $data['UserId'])->find();
      if (empty($hasUser)) {
        $opData['uid'] = 0;
        $opData['username'] = $data['UserId'];
        $opData['ext_log'] = '[企业微信授权]查询不到用户';
        $opData['opstatus'] = -1;
        addOpLog($opData);
        $limitResult = limitResult('managerlogin', $ip);
        if ($limitResult['code'] != -1) {
          return Result::Error('未绑定平台账号');
        } else {
          return Result::Error($limitResult['msg']);
        }
      }
      if ($hasUser['status'] != 1) {
        return Result::Error('用户状态异常或被封禁，请联系上级管理进行处理。');
      }
      if (empty($hasUser['avatar'])) {
        $param['avatar'] = $hasUser['avatar'] = $data['headimgurl'];
      }
      //更新会员状态
      $param = [
        'login_times' => $hasUser['login_times'] + 1,
        'login_ip' => $ip,
        'login_time' => $time,
      ];
      $opData['uid'] = (int) $hasUser['id'];
      $opData['username'] = $hasUser['phone'];
      $opData['ext_log'] = '登录成功';
      $opData['opstatus'] = 1;
      addOpLog($opData);
      Manager::where('id', $hasUser['id'])->update($param);
      $payload['uid']       = $hasUser['id'];
      $payload['password']       = $hasUser['password'];
      $payload['loginTime'] = $time;
      $payload['refresh_key'] = createId();
      $rules = Auth::getRuleId($hasUser['groupId']);
      $tokenArr['rules'] = Auth::getRuleKey($rules);
      $token = think_encrypt(json_encode($payload));
      $tokenArr['userToken'] = $token;
      //用户登录有效期
      $loginExpireTime = config('app.SYS_STATIC.login_expire');
      $loginRefreshExpireTime = config('app.SYS_STATIC.login_refresh_expire');
      // 存储用户token
      $redis->set('token-' . $hasUser['id'], $token, $loginExpireTime);
      $redis->set('refresh:key:' . $payload['refresh_key'], json_encode($payload), $loginRefreshExpireTime);
      $tokenArr['Expire'] = $loginExpireTime * 1000;
      $tokenArr['isSuper'] = $hasUser['is_admin'];
      $tokenArr['username'] = $hasUser['username'];
      $tokenArr['avatar'] = $hasUser['avatar'];
      return Result::Success($tokenArr, '登录成功，页面将自动跳转……');
    }
    return Result::Error('请求不正常');
  }
  public function getLoginParam()
  {
    allowCORS();
    $setting = SysSetting::where('id', 1)->find();
    $return['wechat_login'] = 0;
    $return['oauth_login'] = 0;
    $return['captcha'] = $setting['captcha_type'];
    if (!empty($setting['wechat_appid']) && !empty($setting['wechat_secret'])) {
      $return['wechat_login'] = 1;
      $return['oauth_login'] = 1;
      $return['wechat_appid'] = $setting['wechat_appid'];
    }
    if (!empty($setting['ww_appid']) && !empty($setting['ww_agentid'])) {
      $return['ww_login'] = 1;
      $return['oauth_login'] = 1;
      $return['ww_appid'] = $setting['ww_appid'];
      $return['ww_agentid'] = $setting['ww_agentid'];
    }
    if ($setting['captcha_type'] == 'yp') {
      $return['captcha_app_id'] = $setting['yp_captcha_id'];
    } else if ($setting['captcha_type'] == 'tencent') {
      $return['captcha_app_id'] = $setting['tenc_capt_app_id'];
    }
    return Result::Success($return);
  }
  public function logout()
  {
    return Result::Success([], '退出成功');
  }
  /**
   * 新用户注册
   * @return void
   * @author QianLong <87498106@qq.com>
   * @date 2021-03-27 14:55:13
   * @editAuthor QianLong <87498106@qq.com>
   * @editDescription 
   * @editDate 2021-03-27 14:55:13
   */
  public function doRegister()
  {
    if (request()->isPost()) {
      $ip = get_client_ip();
      $rule = [
        'username|用户名' => 'require',
        'mobile|手机号' => 'require|number',
        'password|密码' => 'require|min:8|max:26',
        'captcha|验证码' => 'require|min:4|max:6',
      ];
      $data = [
        'username'  => input('param.username/s', '', 'trim'),
        'mobile'  => input('param.mobile/s', '', 'trim'),
        'password'  => input('param.password/s', '', 'trim'),
        'captcha'  => input('param.captcha/d', '', 'trim'),
      ];
      $validate = Validate::rule($rule);
      $result   = $validate->check($data);
      if (!$result) {
        return Result::Error($validate->getError());
      }
      $opdata['title'] = '用户注册';
      $time = time();
      $hasUser = Manager::field('id')->where('phone', $data['username'])->find();
      if (!empty($hasUser)) {
        $opdata['uid'] = 0;
        $opdata['username'] = $data['username'];
        $opdata['ext_log'] = $data['username'] . '已注册过';
        $opdata['opstatus'] = -1;
        addOpLog($opdata);
        $limitResult = limitResult('managerregister', $ip);
        if ($limitResult['code'] != -1) {
          return Result::Error('该手机号已注册，如忘记密码，可自行找回。');
        } else {
          return Result::Error($limitResult['msg']);
        }
      }

      $sms_code = $this->redis->get('smsCode:' . $data['username']);
      if (empty($sms_code) || ($sms_code != $data['captcha'])) {
        return Result::Error('验证码已过期或不存在，请重新获取！');
      }
      $this->redis->del('smsCode:' . $data['username']);
      $regdata['phone'] = $data['username'];
      $regdata['salt'] = make_salt();
      $saltPassword = md5($data['password'] . $regdata['salt']);
      $regdata['password'] = $saltPassword;
      $regdata['create_time'] = $time;
      $regdata['status'] = 1;
      $merid = Manager::insertGetId($regdata);
      //更新会员状态
      $opdata['uid'] = (int)$merid;
      $opdata['username'] = $data['username'];
      $opdata['ext_log'] = '注册成功';
      $opdata['opstatus'] = 1;
      addOpLog($opdata);
      return Result::Success([], '注册成功');
    }
    return Result::Error('请求不正常');
  }
  public function doforgotpwd()
  {
    if (request()->isPost()) {
      $rule = [
        'username|手机号' => 'require|number',
        'password|密码' => 'require|min:8|max:26',
        'captcha|验证码' => 'require|min:4|max:6',
      ];
      $data = [
        'username'  => input('param.mobile/s', '', 'trim'),
        'password'  => input('param.password/s', '', 'trim'),
        'captcha'  => input('param.captcha/s', '', 'trim'),
      ];
      $validate = Validate::rule($rule);
      $result   = $validate->check($data);
      if (!$result) {
        return Result::Error($validate->getError());
      }
      $ip = get_client_ip();
      // if (!checkphone($data['username'])) {
      //   return Result::Error('手机号格式不正确');
      // }
      $opdata['title'] = '用户找回密码';
      $time = time();
      $hasUser = Manager::field('id')->where('phone', $data['username'])->find();
      if (empty($hasUser)) {
        $opdata['uid'] = 0;
        $opdata['username'] = $data['username'];
        $opdata['ext_log'] = $data['username'] . ' 用户不存在';
        $opdata['opstatus'] = -1;
        addOpLog($opdata);
        $limitResult = limitResult('managerforgotpwd', $ip);
        if ($limitResult['code'] != -1) {
          return Result::Error('该手机号未注册。');
        } else {
          return Result::Error($limitResult['msg']);
        }
      }

      $sms_code = $this->redis->get('smsCode:' . $data['username']);
      if (empty($sms_code) || ($sms_code != $data['captcha'])) {
        return Result::Error('验证码已过期或不存在，请重新获取！');
      }
      $this->redis->del('smsCode:' . $data['username']);
      $regdata['salt'] = make_salt();
      $saltPassword = md5($data['password'] . $regdata['salt']);
      $regdata['password'] = $saltPassword;
      Manager::where('phone', $data['username'])->update($regdata);
      //更新会员状态
      $opdata['uid'] = (int)$hasUser['id'];
      $opdata['username'] = $data['username'];
      $opdata['ext_log'] = '密码重置成功';
      $opdata['opstatus'] = 1;
      addOpLog($opdata);
      return Result::Success([], '密码重置成功');
    } else {
      return Result::Error('请求不正常');
    }
  }
  /**
   * 获取验证码
   * @return void
   * @author QianLong <87498106@qq.com>
   * @date 2021-03-27 15:07:20
   * @editAuthor QianLong <87498106@qq.com>
   * @editDescription 
   * @editDate 2021-03-27 15:07:20
   */
  public function getSmsCode()
  {
    $phone = input('param.phone/s', '', 'trim');
    $type = input('param.type/s', '', 'trim');
    $token = input('param.token', '', 'trim');
    $authenticate = input('param.authenticate', '', 'trim');
    $ip = get_client_ip();
    if (empty($phone)) {
      return Result::Error('手机号不能为空');
    }
    if (checkphone($phone) != true) {
      return Result::Error('手机号格式不正确');
    }
    $dataVerify['token'] = $token;
    $dataVerify['authenticate'] = $authenticate;
    Verify::check($dataVerify);
    $has_phone = Manager::field('id')->where('phone', $phone)->find();
    if ($type == 'register') {
      if (!empty($has_phone)) {
        $opdata['uid'] = 0;
        $opdata['username'] = $phone;
        $opdata['ext_log'] = '手机号已注册帐号，手机号：' . $phone;
        $opdata['opstatus'] = -1;
        addOpLog($opdata);
        return Result::Error('该手机号已注册帐号，请更换手机号');
      }
    } else if ($type == 'login') {
      if (empty($has_phone)) {
        $opdata['title'] = '用户验证码登录';
        $opdata['uid'] = 0;
        $opdata['username'] = $phone;
        $opdata['ext_log'] = '手机号未注册帐号，手机号：' . $phone;
        $opdata['opstatus'] = -1;
        addOpLog($opdata);
        return Result::Error('该手机号未注册帐号，请确认后重试');
      }
    } else {
      if (empty($has_phone)) {
        $opdata['uid'] = 0;
        $opdata['title'] = '用户找回密码';
        $opdata['username'] = $phone;
        $opdata['ext_log'] = '手机号未注册帐号，手机号：' . $phone;
        $opdata['opstatus'] = -1;
        addOpLog($opdata);
        return Result::Error('该手机号未注册帐号，请确认');
      }
    }

    if ($this->redis->ttl('sms_tj' . $ip) === -1) {
      $this->redis->del('sms_tj' . $ip);
    }
    if ($this->redis->exists('sms_tj' . $ip)) {
      $ipphone = $this->redis->get('sms_tj' . $ip);
      if (($ipphone > 9) && (!empty($ipphone))) {
        $opdata['uid'] = 0;
        $opdata['username'] = $phone;
        $opdata['ext_log'] = '短信码获取频繁，手机号：' . $phone;
        $opdata['opstatus'] = -1;
        addOpLog($opdata);
        return Result::Error('短信码获取频繁，请1小时后重试！');
      } else {
        $this->redis->incr('sms_tj' . $ip);
      }
    } else {
      $this->redis->set('sms_tj' . $ip, 1, 3600);
    }
    $smscode = random_int(1000, 9999);
    $this->redis->set('smsCode:' . $phone, $smscode, 600);
    $smsData['params_json'] = ['code' => $smscode];
    $smsData['st_id'] = '';
    $smsData['phone'] = $phone;
    $sendResult = doSendSms($smsData);
    if (isset($sendResult['code']) && $sendResult['code'] == 200) {
      return Result::Success([], '发送成功');
    } else {
      return Result::Error('发送失败，请稍后重试 [Msg:' . $sendResult['msg'] . ']');
    }
  }
}
